package com.gnetek.netty.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.gnetek.netty.client.EchoClient;
import com.gnetek.netty.contact.Contact;
import com.gnetek.netty.filter.NumberTextFilter;
import com.gnetek.netty.interf.NettyController;
import com.gnetek.netty.thread.DataTransRunner;
import com.gnetek.netty.thread.HeartJumpRunner;
import com.gnetek.netty.utils.GneAlert;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.input.MouseButton;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetAddress;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.ResourceBundle;

/**
 * @Description 控制器
 * @Author Darren Huang
 * @Date 2022-11-11 13:02
 */
public class NettyClientController implements Initializable, NettyController {

    private Logger log = LoggerFactory.getLogger(NettyClientController.class);

    @FXML
    private TextField hostTextField;
    @FXML
    private TextField portTextField;
    @FXML
    private Button connectButton;
    @FXML
    private Button disconnectButton;
    @FXML
    private TextArea sendMsgTextArea;
    @FXML
    private Button sendButton;
//    @FXML
//    private TextArea msgTextArea;
    @FXML
    private TextField heartTimeTextField;
    @FXML
    private Button heartButton;
    @FXML
    private TextField dataTimeTextField;
    @FXML
    private Button dataButton;

    private String settingFilePath = null;

    @FXML
    private WebView browser;
    private WebEngine webEngine;

    private final ContextMenu contextMenu = new ContextMenu();
    MenuItem clearMenuItem = new MenuItem("Clear");

    @Override
    public void initialize(URL location, ResourceBundle resources) {
//        settingFilePath = this.getClass().getClassLoader().getResource("").getPath();
        settingFilePath = System.getProperty("user.dir");
        log.error(settingFilePath);
        if(settingFilePath.startsWith("/")){
            settingFilePath = settingFilePath.substring(1);
        }
        settingFilePath += "/json/setting.json";
        log.error(settingFilePath);

        try {
            hostTextField.setText(InetAddress.getLocalHost().getHostAddress());
            portTextField.setText("9100");
            Platform.runLater(()->connectButton.requestFocus());//获取焦点
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }

        final NumberTextFilter numberTextFilter = new NumberTextFilter();
        portTextField.setTextFormatter(new TextFormatter<String>(numberTextFilter));
        heartTimeTextField.setTextFormatter(new TextFormatter<String>(numberTextFilter));
        dataTimeTextField.setTextFormatter(new TextFormatter<String>(numberTextFilter));

        browser.setContextMenuEnabled(false);
        webEngine = browser.getEngine();

        contextMenu.getItems().add(clearMenuItem);
        browser.setOnMousePressed(m -> {
            if (m.getButton().equals(MouseButton.SECONDARY)) {
                contextMenu.show(browser, m.getScreenX(), m.getScreenY());
            } else {
                contextMenu.hide();
            }
        });

        clearMenuItem.setOnAction(actionEvent -> {
            content = "";
            Platform.runLater(()-> webEngine.loadContent(content));
        });
    }

    /**
     * 点击 连接 或 断开
     * @param event
     * @throws InterruptedException
     */
    @FXML
    public void clickConnect(ActionEvent event) {
        Button button = (Button) event.getSource();
        log.info(button.toString());
        if(button.equals(connectButton)){
            String host = hostTextField.getText();
            String port = portTextField.getText();
            log.info("IP地址：{}，端口号：{}", host, port);
            if (StrUtil.isNotBlank(host) && StrUtil.isNotBlank(port) && StrUtil.isNumeric(port)) {
                connectGUI();
                disconnectButton.setDisable(true);
                heartButton.setDisable(true);
                dataButton.setDisable(true);
                sendButton.setDisable(true);
                new Thread(() -> {
                    if (!EchoClient.create(host, Integer.parseInt(port), this)) {
                        disconnectGUI();
                        GneAlert.showErrorLater("错误", "连接服务器出错", "无法正常连接到服务器。");
                    } else {
                        disconnectButton.setDisable(false);
                        heartButton.setDisable(false);
                        dataButton.setDisable(false);
                        sendButton.setDisable(false);
                    }
                }).start();
            }
        }else if(button.equals(disconnectButton)){
            disconnect();
        }
    }

    /**
     * 打开设置界面
     * @param event
     */
    @FXML
    public void clickOpenSetting(ActionEvent event) {
        // 创建新的stage
        try {
            Parent settingFxml = FXMLLoader.load(getClass().getResource("/fxml/Setting.fxml"));
            Stage settingStage = new Stage();
            settingStage.setTitle("设置参数");
            settingStage.getIcons().add(new Image("/img/bee.png"));
            Scene scene = new Scene(settingFxml);
            settingStage.setScene(scene);//设置场景
            settingStage.setResizable(false);//不能改变窗口大小
            settingStage.show();//显示
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 断开连接
     */
    public void disconnect(){
        Platform.runLater(()-> {
            if ("停止心跳".equals(heartButton.getText())) {
                shutdownHeartJump(heartButton);
            }
            if("停止数据上传".equals(dataButton.getText())){
                shutdownDataTrans(dataButton);
            }
            disconnectGUI();
            new Thread(() -> {
                if (!EchoClient.close()) {
                    connectGUI();
                    GneAlert.showErrorLater("错误", "关闭连接出错", "无法正常断开连接。");
                }
            }).start();
        });
    }

    private void connectGUI(){
        connectButton.setDisable(true);
        disconnectButton.setDisable(false);
        hostTextField.setDisable(true);
        portTextField.setDisable(true);
    }

    private void disconnectGUI(){
        connectButton.setDisable(false);
        disconnectButton.setDisable(true);
        hostTextField.setDisable(false);
        portTextField.setDisable(false);
    }

    /**
     * 点击发送
     * @param event
     */
    @FXML
    public void clickSend(ActionEvent event){
        if(EchoClient.getInstance()!=null && EchoClient.getInstance().isConnent()) {//连接已打开
            String cmd = sendMsgTextArea.getText();
            if (StrUtil.isNotBlank(cmd)) {
                cmd = cmd.replaceAll(" ", "");
                EchoClient.getInstance().sendHexCmd(cmd);
                sendMsgTextArea.clear();
                showMsg(cmd, true);
            }
        }else{
            log.info("没有连接服务器。");
            GneAlert.showErrorLater("错误", "没有连接到服务器", "请先连接到服务器。");
        }
    }

    /**
     * 点击心跳
     * @param event
     */
    @FXML
    public void startHeart(ActionEvent event){
        String settingContent = FileUtil.readString(settingFilePath, "utf-8");
        log.error(settingContent);
        if(StrUtil.isNotBlank(settingContent)) {
            JSONObject setting = JSONUtil.parseObj(settingContent);
            String beehiveId = setting.getStr(Contact.BEEHIVE_ID);
            if(StrUtil.isNotBlank(beehiveId)) {
                if (EchoClient.getInstance() != null && EchoClient.getInstance().isConnent()) {//连接已打开
                    Button button = (Button) event.getSource();
                    if ("启动心跳".equals(button.getText())) {
                        String strSec = heartTimeTextField.getText();
                        if (StrUtil.isNotBlank(strSec)) {
                            button.setText("停止心跳");
                            button.getStyleClass().set(1, "danger");
                            Integer sec = Integer.parseInt(strSec);
                            HeartJumpRunner.doStart(beehiveId, sec, this);
                            heartTimeTextField.setDisable(true);
                        }
                    } else {
                        shutdownHeartJump(button);
                    }
                } else {
                    log.info("没有连接服务器。");
                    GneAlert.showErrorLater("错误", "没有连接到服务器", "请先连接到服务器。");
                }
            }else{
                log.info("没有配置汇总器编号。");
                GneAlert.showErrorLater("错误", "没有配置汇总器编号", "请先点击配置填写汇总器编号。");
            }
        }else {
            log.info("没有配置设备信息。");
            GneAlert.showErrorLater("错误", "没有配置设备信息", "请先点击配置填写设备信息。");
        }
    }


    @FXML
    public void startData(ActionEvent event){
        String settingContent = FileUtil.readString(settingFilePath, "utf-8");
        log.error(settingContent);
        if(StrUtil.isNotBlank(settingContent)) {
            JSONObject setting = JSONUtil.parseObj(settingContent);
            String beehiveId = setting.getStr(Contact.BEEHIVE_ID);
            if(StrUtil.isNotBlank(beehiveId)) {
                String swarmStr = setting.getStr(Contact.SWARM_IDS);
                String honeybeeStr = setting.getStr(Contact.HONEYBEE_IDS);

                if(StrUtil.isNotBlank(swarmStr) && StrUtil.isNotBlank(honeybeeStr)) {

                    if (EchoClient.getInstance() != null && EchoClient.getInstance().isConnent()) {//连接已打开
                        Button button = (Button) event.getSource();
                        if ("启动数据上传".equals(button.getText())) {
                            String strSec = dataTimeTextField.getText();
                            button.setText("停止数据上传");
                            button.getStyleClass().set(1, "danger");
                            Integer min = Integer.parseInt(strSec);
                            DataTransRunner.doStart(swarmStr, honeybeeStr, min, this);
                            dataTimeTextField.setDisable(true);
                        } else {
                            shutdownDataTrans(button);
                        }
                    } else {
                        log.info("没有连接服务器。");
                        GneAlert.showErrorLater("错误", "没有连接到服务器", "请先连接到服务器。");
                    }
                }else {
                    log.info("没有配置采集器和优化器编号。");
                    GneAlert.showErrorLater("错误", "没有配置采集器和优化器编号", "请先点击配置填写采集器和优化器编号。");
                }
            }else{
                log.info("没有配置汇总器编号。");
                GneAlert.showErrorLater("错误", "没有配置汇总器编号", "请先点击配置填写汇总器编号。");
            }
        }else {
            log.info("没有配置设备信息。");
            GneAlert.showErrorLater("错误", "没有配置设备信息", "请先点击配置填写设备信息。");
        }
    }

    /**
     * 关闭心跳信息
     * @param button
     */
    private void shutdownHeartJump(Button button){
        button.setText("启动心跳");
        button.getStyleClass().set(1, "success");
        HeartJumpRunner.doStop();
        heartTimeTextField.setDisable(false);
    }

    /**
     * 关闭数据上传
     * @param button
     */
    private void shutdownDataTrans(Button button) {
        button.setText("启动数据上传");
        button.getStyleClass().set(1, "success");
        DataTransRunner.doStop();
        dataTimeTextField.setDisable(false);
    }

    private String content="";

    /**
     * 显示信息
     * @param msg
     * @param isSend
     */
    public void showMsg(String msg, boolean isSend){
//        String tm = msgTextArea.getText();
//        if(StrUtil.isNotBlank(tm)){
//            tm+="\r\n";
//        }
//        msgTextArea.setText(tm+(isSend?"发送出":"接收到")+"的信息：\r\n"+msg);
//        msgTextArea.positionCaret(msgTextArea.getText().length());//到最底部

        String color = "#FF4500", hr="", str="接收到";
        if(isSend) {
            color="#1E88E5";hr="<hr/>";str="发送出";
        }
        String now = DateUtil.formatDateTime(new Date());
        content="<div style='color:"+color+";word-wrap:break-word;font-size:18px;'>"+str+"的信息("+now+")："+msg+"</div>"+hr+content;
        Platform.runLater(()->webEngine.loadContent(content));

        // 自动回复 开关是否成功 随机
        //AAAA000E000028E501000800FFFF
        if (StrUtil.isNotBlank(msg)) {
            int length = msg.length();
            if (length >= 26) {
                String sqe = msg.substring(8, 18);
                String code = msg.substring(18, 22);
                //AAAA001300000006018008010111111114FFFF
                if ("8008".equals(code) || "8009".equals(code)) {
                    String respCode = "0" + code.substring(1);
                    int success = RandomUtil.randomInt(0, 2);
                    String response = String.format("AAAA000E%s%s%02dFFFF", sqe, respCode, success);

                    try {
                        Thread.sleep(RandomUtil.randomInt(1000, 5000));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }

                    EchoClient.getInstance().sendHexCmd(response);
                    showMsg(response, true);
                } else if ("8001".equals(code)) {
                    String status = msg.substring(22, 24);
                    if ("02".equals(status)) {
                        String response = String.format("AAAA000D%s0003FFFF", sqe);
                        EchoClient.getInstance().sendHexCmd(response);
                        showMsg(response, true);
                    }
                }
            }
        }
    }
}
